﻿using General.Core.Data;
using General.Core.UnitOfWork;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace General.Entities
{
    public class EFRepository<T> : IRepository<T> where T : class
    {
        /// <summary>
        /// 数据上下文
        /// </summary>
        private GeneralDbContext _dbContext;

        /// <summary>
        /// 工作单元
        /// </summary>
        private readonly IUnitOfWork _unitOfWork;

        public EFRepository(GeneralDbContext generalDbContext, IUnitOfWork unitOfWork)
        {
            this._dbContext = generalDbContext;
            _unitOfWork = unitOfWork;
        }

        public DbContext ToRead
        {
            get
            {
                return _dbContext.ToRead();
            }
        }

        public DbContext ToWrite
        {
            get
            {
                return _dbContext.ToWrite();
            }
        }


        public DbContext DbContext
        {
            get
            {
                return _dbContext;
            }
        }



        public DbSet<T> Entities
        {
            get
            {
                return _dbContext.ToRead().Set<T>();
            }
        }
        /// <summary>
        /// 用来组合查询
        /// </summary>
        public IQueryable<T> Table
        {
            get
            {
                return Entities;
            }
        }


        /// <summary>
        /// 执行sql命令
        /// </summary>
        /// <returns></returns>
        public Task<int> ExecuteSqlAsync(string sql)
        {
            return ToWrite.Database.ExecuteSqlRawAsync(sql);
        }



        /// <summary>
        /// 新增方法同步
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public int insert(T entity, bool IsCommit = true)
        {
            ToWrite.Add(entity);
            if (IsCommit)
                return _unitOfWork.Commit();
            else
                return 0;
        }

        public int delete(T entity,bool IsCommit = true)
        {
            ToWrite.Remove(entity);

            if (IsCommit)
                return _unitOfWork.Commit();
            else
                return 0;

        }


        public T getById(object id)
        {
            return ToRead.Set<T>().Find(id);
        }
        public ValueTask<T> getByIdAsync(object id)
        {
            return ToRead.Set<T>().FindAsync(id);
        }


        /// <summary>
        /// 通过Lambda表达式查询实体(异步方式)
        /// </summary>
        /// <param name="query">查询条件(Lambda表达式)</param>
        /// <param name="ignoreQueryFilters">是否忽略过滤器</param>
        /// <returns></returns>
        public Task<T> GetAsync(Expression<Func<T, bool>> query = null, bool ignoreQueryFilters = false)
        {
            if (ignoreQueryFilters)
            {
                return query == null ? ToRead.Set<T>().AsNoTracking().IgnoreQueryFilters().FirstOrDefaultAsync()
                    : ToRead.Set<T>().AsNoTracking().IgnoreQueryFilters().FirstOrDefaultAsync(query);
            }
            else
            {
                return query == null ? ToRead.Set<T>().AsNoTracking().FirstOrDefaultAsync()
                    : ToRead.Set<T>().AsNoTracking().FirstOrDefaultAsync(query);
            }
        }
        /// <summary>
        /// 返回IQueryable集合，延时加载数据
        /// </summary>
        /// <param name="query">查询条件(Lambda表达式)</param>
        /// <param name="ignoreQueryFilters">是否忽略过滤器</param>
        /// <returns></returns>
        public IQueryable<T> GetAllAsync(Expression<Func<T, bool>> query = null, bool ignoreQueryFilters = false)
        {
            if (ignoreQueryFilters)
            {
                return query == null ? ToRead.Set<T>().AsNoTracking().IgnoreQueryFilters()
                    : ToRead.Set<T>().Where(query).AsNoTracking().IgnoreQueryFilters();
            }
            else
            {
                return query == null ? ToRead.Set<T>().AsNoTracking()
                    : ToRead.Set<T>().Where(query).AsNoTracking();
            }
        }
        /// <summary>
        /// 通过Lambda表达式查询实体总数(异步方式)
        /// </summary>
        /// <param name="query">查询条件(Lambda表达式)</param>
        /// <param name="ignoreQueryFilters">是否忽略过滤器</param>
        /// <returns></returns>
        public Task<int> CountAsync(Expression<Func<T, bool>> query = null, bool ignoreQueryFilters = false)
        {
            if (ignoreQueryFilters)
            {
                return query == null ? ToRead.Set<T>().IgnoreQueryFilters().CountAsync()
                    : ToRead.Set<T>().IgnoreQueryFilters().CountAsync(query);
            }
            else
            {
                return query == null ? ToRead.Set<T>().CountAsync()
                    : ToRead.Set<T>().CountAsync(query);
            }
        }

        /// <summary>
        /// 验证当前条件数据库是否存在数据(异步方式)
        /// </summary>
        /// <param name="query">查询条件(Lambda表达式)</param>
        /// <param name="ignoreQueryFilters">是否忽略过滤器</param>
        /// <returns></returns>
        public Task<bool> IsExistAsync(Expression<Func<T, bool>> query = null, bool ignoreQueryFilters = false)
        {
            if (ignoreQueryFilters)
            {
                return query == null ? ToRead.Set<T>().IgnoreQueryFilters().AnyAsync()
                    : ToRead.Set<T>().Where(query).IgnoreQueryFilters().AnyAsync();
            }
            else
            {
                return query == null ? ToRead.Set<T>().AnyAsync()
                    : ToRead.Set<T>().Where(query).AnyAsync();
            }
        }
        /// <summary>
        /// 新增方法异步
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public Task<int> insertAsync(T entity)
        {
            if (entity == null)
            {
                return Task.Run(() => 0);
            }
            ToWrite.Set<T>().Add(entity);
            return ToWrite.SaveChangesAsync();
        }
        /// <summary>
        /// 新增多条异步
        /// </summary>
        /// <param name="lists"></param>
        /// <param name="isCommit"></param>
        /// <returns></returns>
        public Task<int> AddListAsync(List<T> lists)
        {
            if (lists == null || lists.Count <= 0)
            {
                return Task.Run(() => 0);
            }
            ToWrite.Set<T>().AddRange(lists);
            return ToWrite.SaveChangesAsync();
        }
        public Task<int> DeleteAsync(T entity)
        {
            if (entity == null)
            {
                return Task.Run(() => 0);
            }
            ToWrite.Set<T>().Remove(entity);
            return ToWrite.SaveChangesAsync();
        }

        public Task<int> DeleteListAsync(List<T> lists)
        {
            if (lists == null || lists.Count <= 0)
            {
                return Task.Run(() => 0);
            }
            ToWrite.Set<T>().RemoveRange(lists);
            return ToWrite.SaveChangesAsync();
        }
        public int update(T entity)
        {
            ToWrite.Update(entity);
            
            return ToWrite.SaveChanges();
        }
        public Task<int> UpdateAsync(T entity)
        {
            if (entity == null)
            {
                return Task.Run(() => 0);
            }
            ToWrite.Set<T>().Update(entity);

            return ToWrite.SaveChangesAsync();
        }
        public Task<int> UpdateListAsync(List<T> lists)
        {
            if (lists == null || lists.Count <= 0)
            {
                return Task.Run(() => 0);
            }
            ToWrite.Set<T>().UpdateRange(lists);
            return ToWrite.SaveChangesAsync();
        }
    }
}
